import 'dart:math';

import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/material.dart'
    show
        DataRow,
        DataCell,
        DataColumn,
        PaginatedDataTableState,
        PaginatedDataTable,
        DataTableSource;

import '../model/paging_model.dart';

///数据列表行数据回调
typedef DataTableRowCallback<T> = List<DataCell> Function(T row);

///数据列表行已选中回调
typedef DataTableRowSelectableCallback<T> = bool Function(T row);

///数据列表行选中回调
typedef DataTableRowSelectedCallback<T> = void Function(T row, bool selected);

///数据列表
class DataTable<T> extends StatefulWidget {
  final String title;
  final PageModel<T> model;
  final List<DataColumn> columns;
  final bool showCheckboxColumn;
  final List<int>? availableRowsPerPage;
  final DataTableRowCallback<T> onRowCallback;
  final VoidCallback onLoadData;
  final ValueChanged<int>? onPageChanged;
  final ValueChanged<int>? onRowsPerPageChanged;
  final DataTableRowSelectableCallback<T>? onRowSelectableCallback;
  final DataTableRowSelectedCallback<T>? onRowSelectedCallback;

  const DataTable({
    super.key,
    this.title = "",
    required this.model,
    required this.columns,
    this.showCheckboxColumn = false,
    this.availableRowsPerPage,
    required this.onRowCallback,
    required this.onLoadData,
    this.onPageChanged,
    this.onRowsPerPageChanged,
    this.onRowSelectableCallback,
    this.onRowSelectedCallback,
  });

  @override
  State<DataTable<T>> createState() => DataTableState<T>();
}

///数据列表State
class DataTableState<T> extends State<DataTable<T>> {
  final _tableKey = GlobalKey<PaginatedDataTableState>();
  int _rowsPerPage = 10;
  final _ds = _DataSource<T>();
  late List<DataColumn> _columns;

  @override
  void initState() {
    _ds.model = widget.model;
    _ds.model.addListener(() => _loadData());
    _ds.onRowCallback = widget.onRowCallback;
    _ds.onRowSelectableCallback = widget.onRowSelectableCallback;
    _ds.onRowSelectedCallback = widget.onRowSelectedCallback;
    super.initState();
    //
    _columns = widget.columns;
    _columns.insert(0, const DataColumn(label: Text("#")));
  }

  // ///数据行索引跳转
  // void _pageTo(final int rowIndex) {
  //   _tableKey.currentState!.pageTo(rowIndex);
  // }

  ///加载数据
  void _loadData() {
    if (_ds.model.size != _rowsPerPage) {
      setState(() {
        _rowsPerPage = _ds.model.size;
      });
    } else {
      _ds.reload();
    }
  }

  void _onPageChanged(final int firstRowIndex) {
    final changed = widget.onPageChanged;
    if (changed != null) {
      changed(firstRowIndex);
    } else {
      _ds.model.current = (firstRowIndex ~/ _ds.model.size + 1);
    }
    widget.onLoadData();
  }

  void _onRowsPerPageChanged(final int? size) {
    final newSize = size ?? _rowsPerPage;
    final changed = widget.onRowsPerPageChanged;
    if (changed != null) {
      changed(newSize);
    } else {
      _ds.model.size = newSize;
      _ds.model.current = 1;
    }
    widget.onLoadData();
  }

  @override
  Widget build(final BuildContext context) => PaginatedDataTable(
        key: _tableKey,
        header: () {
          final title = widget.title;
          if (title.isNotEmpty) {
            return Text(title);
          }
          return null;
        }(),
        showEmptyRows: false,
        rowsPerPage: _rowsPerPage,
        showCheckboxColumn: widget.showCheckboxColumn,
        availableRowsPerPage: widget.availableRowsPerPage ??
            [
              _rowsPerPage,
              _rowsPerPage * 2,
              _rowsPerPage * 5,
              _rowsPerPage * 10,
            ],
        columns: _columns,
        source: _ds,
        onPageChanged: _onPageChanged,
        onRowsPerPageChanged: _onRowsPerPageChanged,
      );
}

class _DataSource<T> extends DataTableSource {
  var model = PageModel<T>();
  DataTableRowCallback<T>? onRowCallback;
  DataTableRowSelectableCallback<T>? onRowSelectableCallback;
  DataTableRowSelectedCallback<T>? onRowSelectedCallback;

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => model.total;

  @override
  int get selectedRowCount => model.records.where((record) {
        if (onRowSelectableCallback != null) {
          return onRowSelectableCallback!(record);
        }
        return false;
      }).length;

  void reload() {
    notifyListeners();
  }

  List<DataCell> buildRowCells(final T record) {
    if (onRowCallback != null) {
      return onRowCallback!(record);
    }
    return [];
  }

  bool checkedRowSelectable(final T record) {
    if (onRowSelectableCallback != null) {
      return onRowSelectableCallback!(record);
    }
    return false;
  }

  @override
  DataRow? getRow(final int index) {
    final dataIndex = index - model.size * max<int>(model.current - 1, 0);
    if (dataIndex >= model.records.length) {
      return null;
    }
    final record = model.records[dataIndex];
    final cells = buildRowCells(record);
    cells.insert(0, DataCell(Text("${index + 1}")));
    final selected = checkedRowSelectable(record);
    return DataRow.byIndex(
      index: index,
      cells: cells,
      selected: selected,
      onSelectChanged: (sel) {
        if (onRowSelectedCallback != null) {
          onRowSelectedCallback!(record, sel ?? false);
          notifyListeners();
        }
      },
    );
  }
}

///分页排序模型
class PageModel<T> extends ChangeNotifier {
  int total, size, current;
  List<OrderModel> orders;
  List<T> records;

  PageModel({
    this.total = 0,
    this.size = 10,
    this.current = 1,
    this.orders = const [],
    this.records = const [],
  });

  void buildResData(final PagingQueryRes<T> res) {
    total = res.total;
    records = res.rows;
    notifyListeners();
  }

  void buildResItems(final List<T> items) {
    total = items.length;
    records = items;
    notifyListeners();
  }

  PageModel<T> copyWith({
    int? total,
    size,
    current,
    List<OrderModel>? orders,
    List<T>? records,
  }) {
    return PageModel(
      total: total ?? this.total,
      size: size ?? this.size,
      current: current ?? this.current,
      orders: orders ?? this.orders,
      records: records ?? this.records,
    );
  }
}

///排序模型
class OrderModel {
  String? column;
  bool? asc;

  OrderModel({this.column, this.asc});

  OrderModel copyWith({
    final String? column,
    final bool? asc,
  }) {
    return OrderModel(
      column: column ?? this.column,
      asc: asc ?? this.asc,
    );
  }
}
